package scalab.utils
//import scalab.Reporter
import scalab.core.dependencies.Dependency
import java.security.MessageDigest
import java.io.File

object Digest{

	def digest(algorithm: String, str: String): String = {
		val md: MessageDigest = MessageDigest.getInstance(algorithm)
		Hexadecimal.fromByteArray(md.digest(str.getBytes))
	}

	def digest(algorithm: String, strings: Iterable[String]): String = {
		val md: MessageDigest = MessageDigest.getInstance(algorithm)
		strings foreach {s => md.update(s.getBytes)}
		Hexadecimal.fromByteArray(md.digest)
	}

	def digest(algorithm: String, dep: Dependency): String = {
		val md: MessageDigest = MessageDigest.getInstance(algorithm)
		update(md, dep)
		Hexadecimal.fromByteArray(md.digest)
	}

	def digestContent(algorithm: String, f: File): String = {
		val md: MessageDigest = MessageDigest.getInstance(algorithm)
		if(f.exists)
			updateWithContent(md, f)
		Hexadecimal.fromByteArray(md.digest)
	}

	def digestContent(algorithm: String, files: Iterable[File]): String = {
		val md: MessageDigest = MessageDigest.getInstance(algorithm)
		files foreach {f =>	
			if(f.exists)
				updateWithContent(md, f)
		}
		Hexadecimal.fromByteArray(md.digest)
	}

	def digestDependencies(algorithm: String, deps: Iterable[Dependency]): String = {
		val md: MessageDigest = MessageDigest.getInstance(algorithm)
		deps foreach {d => update(md, d)}
		Hexadecimal.fromByteArray(md.digest)
	}

	def update(md: MessageDigest, str: String){
		md.update(str.getBytes)
	}

	def update(md: MessageDigest, strings: Iterable[String]){
		strings foreach {s => md.update(s.getBytes)}
	}

	//def updateDigest(md: MessageDigest, file: File){
	//}

	def update(md: MessageDigest, dep: Dependency){
		val exists = dep.exists
		if(exists)
			updateWithContent(md, dep)
		md.update((dep.canonicalPath + exists + dep.isSoft).getBytes)
	}

	def updateWithDependencies(md: MessageDigest, deps: Iterable[Dependency]){
		deps foreach {d => update(md, d)}
	}

	def updateWithContent(md: MessageDigest, file: File){
		import java.io.{IOException, FileInputStream}
		if(!file.isDirectory){
  		val fis : FileInputStream = new FileInputStream(file)
  		val dataBytes : Array[byte] = new Array(1024) //size the length of the array

			try{
  			var nread : int = fis.read(dataBytes)
  			while (nread > 0) {
    			md.update(dataBytes, 0, nread)
    			nread = fis.read(dataBytes)
  			}
			}
			catch{
				case e : IOException => 
			}
			finally{
				fis.close
			}
		}
	}

	def getHash(md: MessageDigest): String =
		Hexadecimal.fromByteArray(md.digest)

	//md:
	//- file exists
	//- file content
	/*import java.io.FileInputStream
	def digestContent(algorithm: String, files: Iterable[File]): String = {
		val md: MessageDigest = MessageDigest.getInstance(algorithm)
		var nbFiles: Int = 0
		files foreach {f =>
			val exists = f.exists
			if(exists){
  			val fis : FileInputStream = new FileInputStream(f)
  			val dataBytes : Array[byte] = new Array(1024)

				try{
  				var nread : int = fis.read(dataBytes)
  				while (nread > 0) {
    				md.update(dataBytes, 0, nread)
    				nread = fis.read(dataBytes)
  				}
					nbFiles += 1
				}
				catch{
					case e : IOException => 
				}
				finally{
					fis.close
				}
			}
			md.update(exists.toString.getBytes)
		}
		Hexadecimal.fromByteArray(md.digest)
	}
	def digestContent(algorithm: String, files: File*): String = digestContent(algorithm, files)*/

	//md:
	// -dep type
	// -dep path //type+ path = toString
	// -dep exist
	// -dep content
	// -dep isDirectory
	

	

	
}

object MD5{
	val algorithm = "MD5"
	def getMessageDigest: MessageDigest = MessageDigest.getInstance(algorithm)
	def digest(str: String): String = Digest.digest(algorithm, str)
	def digest(strings: Iterable[String]): String = Digest.digest(algorithm, strings)
	//def md5Content(files: File*): String = md5Content(files)
	//def md5Content(files: Iterable[File]): String = digestContent("MD5", files)
	def digest(dep: Dependency): String = Digest.digest(algorithm, dep)
	def digestDependencies(deps: Iterable[Dependency]): String = Digest.digestDependencies(algorithm, deps)
	def digestContent(file: File): String = Digest.digestContent(algorithm, file)
	def digestContent(files: Iterable[File]): String = Digest.digestContent(algorithm, files)
}
